package com.medical.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medical.data.constEnum.CommonEnum;
import com.medical.data.domain.FollowUpPatient;
import com.medical.data.domain.FormTemplate;
import com.medical.data.domain.Patient;
import com.medical.data.domain.User;
import com.medical.data.exception.MyException;
import com.medical.data.mapper.FollowUpPatientMapper;
import com.medical.data.service.*;
import com.medical.data.utils.ResultCode;
import com.medical.data.vo.FollowDataVo;
import com.medical.data.vo.FollowUpDay;
import com.medical.data.vo.GetPatientByDataVo;
import com.medical.data.vo.OpenFollowUpVo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class FollowPatientServiceImpl extends ServiceImpl<FollowUpPatientMapper, FollowUpPatient> implements FollowPatientService {
    @Autowired
    private PatientService patientService;

    @Autowired
    private TokenSerivce tokenSerivce;

    @Autowired
    private FormTemplateService formTemplateService;

    @Autowired
    private HospitalInformationService hospitalInformationService;

    @Autowired
    private PatientTemplateService patientTemplateService;

    @Override
    public void addFollowPatient(OpenFollowUpVo openFollowUpVo, String jsonString, String followfUpNodesString) {
        if (StringUtils.isBlank(jsonString))
            throw new MyException(ResultCode.ERROR.getCode(), "随访节点时间错误");

        //如果更改了随访的开始时间，在表里找到之前的数据，把同个患者的数据删除，在执行新的插入
        User user = tokenSerivce.getUser();
        Boolean isFollowUp = openFollowUpVo.getIsFollowUp();//先查看是开启还是关闭随访
        LambdaQueryWrapper<FollowUpPatient> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(FollowUpPatient::getPatientId, openFollowUpVo.getPatientId());
        //后续判断是否为第一次开启随访时用到
        List<FollowUpPatient> list1 = this.baseMapper.selectList(wrapper1);


        if (!isFollowUp) {
            //关闭随访，把状态未完成的表单关闭
            LambdaUpdateWrapper<FollowUpPatient> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(FollowUpPatient::getPatientId, openFollowUpVo.getPatientId())
                    .eq(FollowUpPatient::getStatus, false)
                    .set(FollowUpPatient::getIsDown, true); // 设置要更新的字段及值

            int update = this.baseMapper.update(null, lambdaUpdateWrapper);
            if (update < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新关闭开启字段失败");
            }
        } else if (ObjectUtils.isEmpty(list1)) {
            //如果是第一次开启随访
            Patient patient = patientService.getPatientById(openFollowUpVo.getPatientId());
            LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FollowUpPatient::getPatientId, openFollowUpVo.getPatientId());
            String times = jsonString;//2024-03-21,2024-03-15,2024-03-24,2024-03-19,2024-03-28
            String[] timesArray = times.split(",");
            String[] nodesArray = followfUpNodesString.split(",");
            List<FollowUpPatient> list = new ArrayList<>();
            for (int i = 0; i < timesArray.length; i++) {

                String time = timesArray[i];
                String node = nodesArray[i];

                FollowUpPatient followUpPatient = new FollowUpPatient();
                followUpPatient.setPatientId(patient.getId());
                followUpPatient.setName(patient.getPatientName());
                followUpPatient.setProjectId(patient.getProjectId());
                followUpPatient.setIdCard(patient.getIdCard());
                followUpPatient.setDiseaseType(patient.getDiseaseType());
                followUpPatient.setDoctorName(user.getNickName());
                followUpPatient.setInTime(patient.getInTime());
                followUpPatient.setOutTime(patient.getOutTime());
                followUpPatient.setStatus(patient.getStatus());
                followUpPatient.setDoctorId(patient.getDoctorId());
                followUpPatient.setFollowUpTime(time);
                followUpPatient.setNodeId(node);
                followUpPatient.setNodeName(formTemplateService.getNameByNodeId(node));

                list.add(followUpPatient);
            }
            this.saveBatch(list);

        } else {
            //把isDown字段改为0
            LambdaUpdateWrapper<FollowUpPatient> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(FollowUpPatient::getPatientId, openFollowUpVo.getPatientId())
                    .eq(FollowUpPatient::getStatus, false)
                    .set(FollowUpPatient::getIsDown, false); // 设置要更新的字段及值

            int update = this.baseMapper.update(null, lambdaUpdateWrapper);
            if (update < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新关闭开启字段失败");
            }
        }

    }

    @Override
    public Map<String, Object> getPatientByDate(GetPatientByDataVo getPatientByDataVo) {
        List<String> dateList = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = getPatientByDataVo.getBeginTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endDate = getPatientByDataVo.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        while (!startDate.isAfter(endDate)) {
            dateList.add(startDate.format(formatter));
            startDate = startDate.plusDays(1);
        }
        Map<String, Object> resultMap = new LinkedHashMap<>(); // 使用LinkedHashMap保持顺序
        for (String data : dateList) {
            Map<String, Object> resultMap1 = new HashMap<>();
            LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FollowUpPatient::getFollowUpTime, data)
                    .eq(FollowUpPatient::getIsDown, false);
            List<FollowUpPatient> list = this.baseMapper.selectList(wrapper);
            if (ObjectUtils.isEmpty(list)) {
                resultMap1.put("data", data);
                resultMap1.put("number", 0);
                resultMap1.put("list", null);
            } else {
                resultMap1.put("data", data);
                resultMap1.put("number", list.size());
                resultMap1.put("list", list);
            }
            resultMap.put(data, resultMap1); // 使用日期作为键存储每天的数据
        }
        return resultMap;
    }

    @Override
    public void updateStatus(String nodeId, String patientId) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getNodeId, nodeId)
                .eq(FollowUpPatient::getPatientId, patientId);
        FollowUpPatient followUpPatient = this.baseMapper.selectOne(wrapper);
        followUpPatient.setStatus(true);
        int update = this.baseMapper.updateById(followUpPatient);
        if (update < 1) {
            throw new MyException(ResultCode.ERROR.getCode(), "更新完成状态失败");
        }
    }

    @Override
    public void updateIsDown(String patientId, boolean isDown) {
        //把未完成的表单全部关闭
        LambdaUpdateWrapper<FollowUpPatient> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(FollowUpPatient::getPatientId, patientId)
                .eq(FollowUpPatient::getStatus, false)
                .set(FollowUpPatient::getIsDown, isDown);
        int update = this.baseMapper.update(null, wrapper);
        if (update < 1) {
            throw new MyException(ResultCode.ERROR.getCode(), "更新随访是否关闭失败");
        }
    }

    @Override
    public Map<String, Object> getPatientByDay(FollowUpDay followUpDay) {
        Integer currentPage = CommonEnum.OTHER_PATIENT_CURRENT.getValue();
        Integer pageSize = CommonEnum.OTHER_PATIENT_LIMIT.getValue();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String date = sdf.format(followUpDay.getDay());

        if (!org.apache.commons.lang3.ObjectUtils.isEmpty(followUpDay.getCurrent())) {
            currentPage = followUpDay.getCurrent();
        }
        if (!org.apache.commons.lang3.ObjectUtils.isEmpty(followUpDay.getLimit())) {
            pageSize = followUpDay.getLimit();
        }
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getFollowUpTime, date)
                .eq(FollowUpPatient::getIsDown, false);
        Page<FollowUpPatient> page = new Page<>(currentPage, pageSize);
        baseMapper.selectPage(page, wrapper);//baseMapper.selectList(wrapper);
        List<FollowUpPatient> records = page.getRecords();
        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());
        map.put("current", page.getCurrent());
        map.put("patients", records);
        return map;
    }

    //用于判断患者是否有随访的表单
    @Override
    public Boolean isExistPatient(String patientId) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getPatientId, patientId);
        List<FollowUpPatient> list = this.baseMapper.selectList(wrapper);
        if (list.size() == 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void addPatient(FollowUpPatient followUpPatient) {
        String hospitalId = followUpPatient.getHospitalName();
        followUpPatient.setHospitalName(hospitalInformationService.getNameById(hospitalId));
        int insert = this.baseMapper.insert(followUpPatient);
        if (insert < 1) {
            throw new MyException(ResultCode.ERROR.getCode(), "插入随访患者失败");
        }
    }

    @Override
    public void updateIsDownAndTime(String patientId, Date followUpTime, boolean isDown) {
        //先找到未完成的节点
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getPatientId, patientId)
                .eq(FollowUpPatient::getStatus, false)
                .eq(FollowUpPatient::getIsDown, false);
        List<FollowUpPatient> list = this.baseMapper.selectList(wrapper);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (FollowUpPatient followUpPatient : list) {
            String nodeId = followUpPatient.getNodeId();
            FormTemplate formTemplate = formTemplateService.getNodeById(nodeId);
            String days = formTemplate.getFollowUpTime();
            int daysToAdd = Integer.parseInt(days); // 将 String 类型的天数转换为整数
            long timeInMillis = followUpTime.getTime() + daysToAdd * 24 * 60 * 60 * 1000; // 计算新的随访时间的毫秒数
            Date newFollowUpTime = new Date(timeInMillis); // 创建新的随访时间对象
            String dateString = sdf.format(newFollowUpTime);
            LambdaUpdateWrapper<FollowUpPatient> wrapper1 = new LambdaUpdateWrapper<>();
            wrapper1.eq(FollowUpPatient::getId, followUpPatient.getId())
                    .set(FollowUpPatient::getFollowUpTime, dateString);
            int update = this.baseMapper.update(null, wrapper1);
            if (update < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "更新新的随访时间失败");
            }
        }
    }

    @Override
    public Map<String, Object> getPatientStatus() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String followUpTime = sdf.format(date);
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getFollowUpTime, followUpTime)
                .eq(FollowUpPatient::getIsDown, false);
        List<FollowUpPatient> list = this.baseMapper.selectList(wrapper);
        int finish = 0;
        int noFinish = list.size();
        for (FollowUpPatient followUpPatient : list) {
            if (followUpPatient.getStatus()) {
                finish++;
                noFinish--;
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("finish", finish);
        map.put("noFinish", noFinish);
        return map;
    }

    @Override
    public FollowUpPatient getPatientById(String id) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getId, id);
        return this.baseMapper.selectOne(wrapper);
    }

    @Override
    public void updateRemindStatus(String id) {
        LambdaUpdateWrapper<FollowUpPatient> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(FollowUpPatient::getId, id)
                .set(FollowUpPatient::getIsRemind, true);
        int update = this.baseMapper.update(null, wrapper);
        if (update < 1) {
            throw new MyException(ResultCode.ERROR.getCode(), "更新提醒状态失败");
        }

    }

    @Override
    public Boolean getRemindById(String id) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getId, id);
        return this.baseMapper.selectOne(wrapper).getIsRemind();
    }

    @Override
    public void deleteFollowPatientById(String patientId) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getPatientId, patientId);
        List<FollowUpPatient> list = this.baseMapper.selectList(wrapper);
        if (list.size() != 0) {
            int delete = this.baseMapper.delete(wrapper);
            if (delete < 1) {
                throw new MyException(ResultCode.ERROR.getCode(), "删除随访患者失败");
            }
        }
    }

    @Override
    public int getFollowFinishNumber() {
        User user = tokenSerivce.getUser();
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getDoctorId, user.getId())
                .eq(FollowUpPatient::getStatus, "1")
                .eq(FollowUpPatient::getIsDown, "0"); // 使用DATE()函数比较日期部分;
        return this.baseMapper.selectList(wrapper).size();
    }

    @Override
    public int getTodayFollowFinishNumber() {
        User user = tokenSerivce.getUser();
        LocalDate today = LocalDate.now();
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getDoctorId, user.getId())
                .eq(FollowUpPatient::getStatus, "1")
                .eq(FollowUpPatient::getIsDown, "0")
                .apply("DATE(create_time) = DATE({0})", today); // 使用DATE()函数比较日期部分;
        return this.baseMapper.selectList(wrapper).size();
    }

    @Override
    public int getFollowNoFinishNumber() {
        User user = tokenSerivce.getUser();
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getDoctorId, user.getId())
                .eq(FollowUpPatient::getStatus, "0")
                .eq(FollowUpPatient::getIsDown, "0"); // 使用DATE()函数比较日期部分;
        return this.baseMapper.selectList(wrapper).size();
    }

    @Override
    public int getTodayNoFollowFinishNumber() {
        User user = tokenSerivce.getUser();
        LocalDate today = LocalDate.now();
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getDoctorId, user.getId())
                .eq(FollowUpPatient::getStatus, "0")
                .eq(FollowUpPatient::getIsDown, "0")
                .apply("DATE(create_time) = DATE({0})", today); // 使用DATE()函数比较日期部分;
        return this.baseMapper.selectList(wrapper).size();
    }

    @Override
    public FollowDataVo getFollowUpData(String id, String nodeId) {
        LambdaQueryWrapper<FollowUpPatient> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FollowUpPatient::getPatientId, id)
                .eq(FollowUpPatient::getNodeId, nodeId);
        FollowUpPatient followUpPatient = this.baseMapper.selectOne(wrapper);
        FollowDataVo followDataVo = new FollowDataVo();
        followDataVo.setNodeName(followUpPatient.getNodeName());
        followDataVo.setStatus(patientTemplateService.getFinishStatus(followUpPatient.getPatientId(), followUpPatient.getNodeId()));
        followDataVo.setFollowUpTime(followUpPatient.getFollowUpTime());
        followDataVo.setIsDown(followUpPatient.getIsDown());

        return followDataVo;
    }

}
